// 《围棋》作者版权所有。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// go:build ignore 
// +build ignore 

package main

import "strings"

// /注意：
// -整数类型位于寄存器的低部分。上部是垃圾。
// /-布尔类型使用寄存器的低位字节。0=假，1=真。
// 高位字节是垃圾。
// /-*常量指令可能使用大于指令编码的常数。
// 在本例中，汇编程序扩展为多条指令，并使用tmp 
// 寄存器（R27）。

// 后缀对各种指令的位宽度进行编码。
// D（双字）=64位
// W（字）=32位
// H（半字）=16位
// HU=16位无符号
// B（字节）=8位
// BU 8位无符号
// S（单字）=32位浮点
// D（双字）=64位浮点

// 因此，regmask保持在int64 
// 手动编码regmask时要小心。
var regNamesARM64 = []string{
	"R0",
	"R1",
	"R2",
	"R3",
	"R4",
	"R5",
	"R6",
	"R7",
	"R8",
	"R9",
	"R10",
	"R11",
	"R12",
	"R13",
	"R14",
	"R15",
	"R16",
	"R17",
	"R18", // 平台寄存器，未使用
	"R19",
	"R20",
	"R21",
	"R22",
	"R23",
	"R24",
	"R25",
	"R26",
	// R27=REGTMP未在regalloc 
	"g",   // 又名R28 
	"R29", // 帧指针，未使用
	"R30", // 又名REGLINK 
	"SP",  // 又名R31 

	"F0",
	"F1",
	"F2",
	"F3",
	"F4",
	"F5",
	"F6",
	"F7",
	"F8",
	"F9",
	"F10",
	"F11",
	"F12",
	"F13",
	"F14",
	"F15",
	"F16",
	"F17",
	"F18",
	"F19",
	"F20",
	"F21",
	"F22",
	"F23",
	"F24",
	"F25",
	"F26",
	"F27",
	"F28",
	"F29",
	"F30",
	"F31",

	// 如果添加寄存器，请在运行时更新asyncPreempt。

	// 伪寄存器
	"SB",
}

func init() {
	// 将注册表名映射到注册表整数。
	if len(regNamesARM64) > 64 {
		panic("too many registers")
	}
	num := map[string]int{}
	for i, name := range regNamesARM64 {
		num[name] = i
	}
	buildReg := func(s string) regMask {
		m := regMask(0)
		for _, r := range strings.Split(s, " ") {
			if n, ok := num[r]; ok {
				m |= regMask(1) << uint(n)
				continue
			}
			panic("register " + r + " not found")
		}
		return m
	}

	// 通用单个寄存器掩码
	var (
		gp         = buildReg("R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30")
		gpg        = gp | buildReg("g")
		gpsp       = gp | buildReg("SP")
		gpspg      = gpg | buildReg("SP")
		gpspsbg    = gpspg | buildReg("SB")
		fp         = buildReg("F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31")
		callerSave = gp | fp | buildReg("g") // 运行时。setg（以及任何称呼它的）可能会重击g 
		r0         = buildReg("R0")
		r1         = buildReg("R1")
		r2         = buildReg("R2")
		r3         = buildReg("R3")
	)
	// Common regInfo 
	var (
		gp01           = regInfo{inputs: nil, outputs: []regMask{gp}}
		gp0flags1      = regInfo{inputs: []regMask{0}, outputs: []regMask{gp}}
		gp11           = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp}}
		gp11sp         = regInfo{inputs: []regMask{gpspg}, outputs: []regMask{gp}}
		gp1flags       = regInfo{inputs: []regMask{gpg}}
		gp1flags1      = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp}}
		gp11flags      = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp, 0}}
		gp21           = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{gp}}
		gp21nog        = regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp}}
		gp21flags      = regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp, 0}}
		gp2flags       = regInfo{inputs: []regMask{gpg, gpg}}
		gp2flags1      = regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp}}
		gp2flags1flags = regInfo{inputs: []regMask{gp, gp, 0}, outputs: []regMask{gp, 0}}
		gp2load        = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{gp}}
		gp22           = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{gp, gp}}
		gp31           = regInfo{inputs: []regMask{gpg, gpg, gpg}, outputs: []regMask{gp}}
		gpload         = regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{gp}}
		gpstore        = regInfo{inputs: []regMask{gpspsbg, gpg}}
		gpstore0       = regInfo{inputs: []regMask{gpspsbg}}
		gpstore2       = regInfo{inputs: []regMask{gpspsbg, gpg, gpg}}
		gpxchg         = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{gp}}
		gpcas          = regInfo{inputs: []regMask{gpspsbg, gpg, gpg}, outputs: []regMask{gp}}
		fp01           = regInfo{inputs: nil, outputs: []regMask{fp}}
		fp11           = regInfo{inputs: []regMask{fp}, outputs: []regMask{fp}}
		fpgp           = regInfo{inputs: []regMask{fp}, outputs: []regMask{gp}}
		gpfp           = regInfo{inputs: []regMask{gp}, outputs: []regMask{fp}}
		fp21           = regInfo{inputs: []regMask{fp, fp}, outputs: []regMask{fp}}
		fp31           = regInfo{inputs: []regMask{fp, fp, fp}, outputs: []regMask{fp}}
		fp2flags       = regInfo{inputs: []regMask{fp, fp}}
		fp1flags       = regInfo{inputs: []regMask{fp}}
		fpload         = regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{fp}}
		fp2load        = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{fp}}
		fpstore        = regInfo{inputs: []regMask{gpspsbg, fp}}
		fpstore2       = regInfo{inputs: []regMask{gpspsbg, gpg, fp}}
		readflags      = regInfo{inputs: nil, outputs: []regMask{gp}}
		prefreg        = regInfo{inputs: []regMask{gpspsbg}}
	)
	ops := []opData{
		// binary ops 
		{name: "ADCSflags", argLength: 3, reg: gp2flags1flags, typ: "(UInt64,Flags)", asm: "ADCS", commutative: true}, // arg0+arg1+carry，设置标志。
		{name: "ADCzerocarry", argLength: 1, reg: gp0flags1, typ: "UInt64", asm: "ADC"},                               // ZR+ZR+携带
		{name: "ADD", argLength: 2, reg: gp21, asm: "ADD", commutative: true},                                         // arg0+arg1 
		{name: "ADDconst", argLength: 1, reg: gp11sp, asm: "ADD", aux: "Int64"},                                       // arg0+生长素
		{name: "ADDSconstflags", argLength: 1, reg: gp11flags, typ: "(UInt64,Flags)", asm: "ADDS", aux: "Int64"},      // arg0+生长素，设置标志。
		{name: "ADDSflags", argLength: 2, reg: gp21flags, typ: "(UInt64,Flags)", asm: "ADDS", commutative: true},      // arg0+arg1，设置标志。
		{name: "SUB", argLength: 2, reg: gp21, asm: "SUB"},                                                            // arg0-arg1 
		{name: "SUBconst", argLength: 1, reg: gp11, asm: "SUB", aux: "Int64"},                                         // arg0-auxInt 
		{name: "SBCSflags", argLength: 3, reg: gp2flags1flags, typ: "(UInt64,Flags)", asm: "SBCS"},                    // arg0-（arg1+借用），设置标志。
		{name: "SUBSflags", argLength: 2, reg: gp21flags, typ: "(UInt64,Flags)", asm: "SUBS"},                         // arg0-arg1，设置标志。
		{name: "MUL", argLength: 2, reg: gp21, asm: "MUL", commutative: true},                                         // arg0*arg1 
		{name: "MULW", argLength: 2, reg: gp21, asm: "MULW", commutative: true},                                       // arg0*arg1，32位
		{name: "MNEG", argLength: 2, reg: gp21, asm: "MNEG", commutative: true},                                       // -arg0*arg1 
		{name: "MNEGW", argLength: 2, reg: gp21, asm: "MNEGW", commutative: true},                                     // -arg0*arg1，32位
		{name: "MULH", argLength: 2, reg: gp21, asm: "SMULH", commutative: true},                                      // （arg0*arg1）>>64，有符号
		{name: "DIV", argLength: 2, reg: gp21, asm: "SDIV"},                                                           // arg0/arg1，有符号
		{name: "UDIV", argLength: 2, reg: gp21, asm: "UDIV"},                                                          // arg0/arg1，无符号
		{name: "DIVW", argLength: 2, reg: gp21, asm: "SDIVW"},                                                         // arg0/arg1，有符号，32位
		{name: "UDIVW", argLength: 2, reg: gp21, asm: "UDIVW"},                                                        // arg0/arg1，无符号，32位
		{name: "MOD", argLength: 2, reg: gp21, asm: "REM"},                                                            // arg0%arg1，有符号

		{name: "FADDS", argLength: 2, reg: fp21, asm: "FADDS", commutative: true},   // arg0+arg1 
		{name: "FADDD", argLength: 2, reg: fp21, asm: "FADDD", commutative: true},   // arg0+arg1 
		{name: "FSUBS", argLength: 2, reg: fp21, asm: "FSUBS"},                      // arg0-arg1 
		{name: "FSUBD", argLength: 2, reg: fp21, asm: "FSUBD"},                      // arg0-arg1 
		{name: "FMULS", argLength: 2, reg: fp21, asm: "FMULS", commutative: true},   // arg0*arg1 
		{name: "FMULD", argLength: 2, reg: fp21, asm: "FMULD", commutative: true},   // arg0*arg1 
		{name: "FNMULS", argLength: 2, reg: fp21, asm: "FNMULS", commutative: true}, // /-（arg0*arg1）

		{name: "OR", argLength: 2, reg: gp21, asm: "ORR", commutative: true},  // arg0 | arg1 
		{name: "ORconst", argLength: 1, reg: gp11, asm: "ORR", aux: "Int64"},  // arg0 |生长素
		{name: "XOR", argLength: 2, reg: gp21, asm: "EOR", commutative: true}, // arg0 ^ arg1 
		{name: "XORconst", argLength: 1, reg: gp11, asm: "EOR", aux: "Int64"}, // arg0 ^生长素
		{name: "BIC", argLength: 2, reg: gp21, asm: "BIC"},                    // arg0和^ arg1 
		{name: "EON", argLength: 2, reg: gp21, asm: "EON"},                    // arg0 ^^ arg1 


		// 一元运算
		{name: "MVN", argLength: 1, reg: gp11, asm: "MVN"},                                    // /^arg0 
		{name: "NEG", argLength: 1, reg: gp11, asm: "NEG"},                                    // /-arg0 
		{name: "NEGSflags", argLength: 1, reg: gp11flags, typ: "(UInt64,Flags)", asm: "NEGS"}, // /-arg0，设置标志。
		{name: "NGCzerocarry", argLength: 1, reg: gp0flags1, typ: "UInt64", asm: "NGC"},       // /-1如果借款，否则为0。
		{name: "FABSD", argLength: 1, reg: fp11, asm: "FABSD"},                                // abs（arg0），float64 
		{name: "FNEGS", argLength: 1, reg: fp11, asm: "FNEGS"},                                // -arg0，float32 
		{name: "FNEGD", argLength: 1, reg: fp11, asm: "FNEGD"},                                // -arg0，float64 
		{name: "FSQRTD", argLength: 1, reg: fp11, asm: "FSQRTD"},                              // sqrt（arg0），float64 
		{name: "FSQRTS", argLength: 1, reg: fp11, asm: "FSQRTS"},                              // sqrt（arg0），float32 
		{name: "REV", argLength: 1, reg: gp11, asm: "REV"},                                    // 字节反转，64位
		{name: "REVW", argLength: 1, reg: gp11, asm: "REVW"},                                  // 字节反转，32位
		{name: "REV16", argLength: 1, reg: gp11, asm: "REV16"},                                // 16位半字中的字节反转，64位
		{name: "REV16W", argLength: 1, reg: gp11, asm: "REV16W"},                              // 每个16位半字中的字节反转，32位
		{name: "RBIT", argLength: 1, reg: gp11, asm: "RBIT"},                                  // 位反转，64位
		{name: "RBITW", argLength: 1, reg: gp11, asm: "RBITW"},                                // 位反转，32位
		{name: "CLZ", argLength: 1, reg: gp11, asm: "CLZ"},                                    // 计数前导零，64位
		{name: "CLZW", argLength: 1, reg: gp11, asm: "CLZW"},                                  // 计数前导零，32位
		{name: "VCNT", argLength: 1, reg: fp11, asm: "VCNT"},                                  // 计算每个8位单元的设置位，并将结果存储在每个8位单元
		{name: "VUADDLV", argLength: 1, reg: fp11, asm: "VUADDLV"},                            // 64位值中八个字节的无符号和，零扩展到64位。
		{name: "LoweredRound32F", argLength: 1, reg: fp11, resultInArg0: true, zeroWidth: true},
		{name: "LoweredRound64F", argLength: 1, reg: fp11, resultInArg0: true, zeroWidth: true},

		// 3-操作数，加数先到
		{name: "FMADDS", argLength: 3, reg: fp31, asm: "FMADDS"},   // +arg0+（arg1*arg2）
		{name: "FMADDD", argLength: 3, reg: fp31, asm: "FMADDD"},   // /+arg0+（arg1*arg2）
		{name: "FNMADDS", argLength: 3, reg: fp31, asm: "FNMADDS"}, // -arg0-（arg1*arg2）
		{name: "FNMADDD", argLength: 3, reg: fp31, asm: "FNMADDD"}, // /-arg0-（arg1*arg2）
		{name: "FMSUBS", argLength: 3, reg: fp31, asm: "FMSUBS"},   // /+arg0-（arg1*arg2）
		{name: "FMSUBD", argLength: 3, reg: fp31, asm: "FMSUBD"},   // /+arg0-（arg1*arg2）
		{name: "MSUB", argLength: 3, reg: gp31, asm: "MSUB"},       // /+arg0-（arg1*arg2）
		{name: "MSUBW", argLength: 3, reg: gp31, asm: "MSUBW"},     // /+arg0-（arg1*arg2），32位

		// 移位
		{name: "SLL", argLength: 2, reg: gp21, asm: "LSL"},                        // arg0<<arg1，移位量为mod 64 
		{name: "SLLconst", argLength: 1, reg: gp11, asm: "LSL", aux: "Int64"},     // arg0<<auxInt，auxInt应在0到63之间。
		{name: "SRL", argLength: 2, reg: gp21, asm: "LSR"},                        // arg0>>arg1，未签名，移位量为mod 64 
		{name: "SRLconst", argLength: 1, reg: gp11, asm: "LSR", aux: "Int64"},     // arg0>>生长素，未签名，生长素应在0到63之间。
		{name: "SRA", argLength: 2, reg: gp21, asm: "ASR"},                        // arg0>>arg1，签名，移位量为mod 64 
		{name: "SRAconst", argLength: 1, reg: gp11, asm: "ASR", aux: "Int64"},     // arg0>>生长素，签名，生长素应在0到63之间。
		{name: "ROR", argLength: 2, reg: gp21, asm: "ROR"},                        // arg0按（arg1 mod 64）位右转
		{name: "RORW", argLength: 2, reg: gp21, asm: "RORW"},                      // arg0按（arg1 mod 32）位右转
		{name: "RORconst", argLength: 1, reg: gp11, asm: "ROR", aux: "Int64"},     // arg0按生长素位右转，生长素应在0到63之间。
		{name: "RORWconst", argLength: 1, reg: gp11, asm: "RORW", aux: "Int64"},   // uint32（arg0）通过生长素位右旋转，生长素应该在0到31之间。
		{name: "EXTRconst", argLength: 2, reg: gp21, asm: "EXTR", aux: "Int64"},   // 从arg0中提取64位：arg1从lsb auxInt开始，auxInt应该在0到63之间。
		{name: "EXTRWconst", argLength: 2, reg: gp21, asm: "EXTRW", aux: "Int64"}, // 从arg0[31:0]中提取32位：arg1[31:0]从lsb auxInt开始，并且顶部32位为零，auxInt应该在0到31之间。

		// 比较
		{name: "CMP", argLength: 2, reg: gp2flags, asm: "CMP", typ: "Flags"},                      // arg0与arg1 
		{name: "CMPconst", argLength: 1, reg: gp1flags, asm: "CMP", aux: "Int64", typ: "Flags"},   // arg0与生长素
		{name: "CMPW", argLength: 2, reg: gp2flags, asm: "CMPW", typ: "Flags"},                    // arg0与arg1比较，32位
		{name: "CMPWconst", argLength: 1, reg: gp1flags, asm: "CMPW", aux: "Int32", typ: "Flags"}, // arg0与生长素比较，32位
		{name: "CMNconst", argLength: 1, reg: gp1flags, asm: "CMN", aux: "Int64", typ: "Flags"},   // arg0与-auxInt 
		{name: "CMNWconst", argLength: 1, reg: gp1flags, asm: "CMNW", aux: "Int32", typ: "Flags"}, // arg0与-auxInt比较，32位
		{name: "TST", argLength: 2, reg: gp2flags, asm: "TST", typ: "Flags", commutative: true},   // arg0和arg1与0 
		{name: "TSTconst", argLength: 1, reg: gp1flags, asm: "TST", aux: "Int64", typ: "Flags"},   // arg0和auxInt与0 
		{name: "TSTW", argLength: 2, reg: gp2flags, asm: "TSTW", typ: "Flags", commutative: true}, // arg0和arg1与0比较，32位
		{name: "TSTWconst", argLength: 1, reg: gp1flags, asm: "TSTW", aux: "Int32", typ: "Flags"}, // arg0和auxInt与0比较，32位
		{name: "FCMPS", argLength: 2, reg: fp2flags, asm: "FCMPS", typ: "Flags"},                  // arg0与arg1比较，32 
		{name: "FCMPS0", argLength: 1, reg: fp1flags, asm: "FCMPS", typ: "Flags"},                 // arg0与0比较，float32-
		{name: "FCMPD0", argLength: 1, reg: fp1flags, asm: "FCMPD", typ: "Flags"},                 // arg0与0比较，float64-

		// /移位操作
		{name: "MVNshiftLL", argLength: 1, reg: gp11, asm: "MVN", aux: "Int64"},                   // ^（arg0<生长素），生长素应在0到63之间。
		{name: "MVNshiftRL", argLength: 1, reg: gp11, asm: "MVN", aux: "Int64"},                   // /^（arg0>>生长素），无符号移位，生长素应在0到63之间。
		{name: "MVNshiftRA", argLength: 1, reg: gp11, asm: "MVN", aux: "Int64"},                   // /^（arg0>>生长素），标记移位，生长素应在0到63之间。
		{name: "MVNshiftRO", argLength: 1, reg: gp11, asm: "MVN", aux: "Int64"},                   // /^（arg0 ROR生长素），标记移位，生长素应在0到63之间。
		{name: "NEGshiftLL", argLength: 1, reg: gp11, asm: "NEG", aux: "Int64"},                   // /-（arg0<<生长素），生长素应在0到63之间。
		{name: "NEGshiftRL", argLength: 1, reg: gp11, asm: "NEG", aux: "Int64"},                   // /-（arg0>>生长素），无符号移位，生长素应在0到63之间。
		{name: "NEGshiftRA", argLength: 1, reg: gp11, asm: "NEG", aux: "Int64"},                   // /-（arg0>>生长素），标记移位，生长素应在0到63之间。
		{name: "ADDshiftLL", argLength: 2, reg: gp21, asm: "ADD", aux: "Int64"},                   // arg0+arg1<<生长素，生长素应该在0到63之间。
		{name: "ADDshiftRL", argLength: 2, reg: gp21, asm: "ADD", aux: "Int64"},                   // arg0+arg1>>生长素，无符号移位，生长素应在0到63之间。
		{name: "ADDshiftRA", argLength: 2, reg: gp21, asm: "ADD", aux: "Int64"},                   // arg0+arg1>>生长素，符号移位，生长素应在0到63之间。
		{name: "SUBshiftLL", argLength: 2, reg: gp21, asm: "SUB", aux: "Int64"},                   // arg0-arg1<<生长素，生长素应该在0到63之间。
		{name: "SUBshiftRL", argLength: 2, reg: gp21, asm: "SUB", aux: "Int64"},                   // arg0-arg1>>生长素，无符号移位，生长素应该在0到63之间。
		{name: "SUBshiftRA", argLength: 2, reg: gp21, asm: "SUB", aux: "Int64"},                   // arg0-arg1>>生长素，符号移位，生长素应在0到63之间。
		{name: "ANDshiftLL", argLength: 2, reg: gp21, asm: "AND", aux: "Int64"},                   // arg0&（arg1<<生长素），生长素应该在0到63之间。
		{name: "ANDshiftRL", argLength: 2, reg: gp21, asm: "AND", aux: "Int64"},                   // arg0&（arg1>>生长素），无符号移位，生长素应在0到63之间。
		{name: "ANDshiftRA", argLength: 2, reg: gp21, asm: "AND", aux: "Int64"},                   // arg0&（arg1>>生长素），符号移位，生长素应在0到63之间。
		{name: "ANDshiftRO", argLength: 2, reg: gp21, asm: "AND", aux: "Int64"},                   // arg0&（arg1 ROR生长素），符号移位，生长素应在0到63之间。
		{name: "ORshiftLL", argLength: 2, reg: gp21, asm: "ORR", aux: "Int64"},                    // arg0 | arg1<<生长素，生长素应在0到63之间。
		{name: "ORshiftRL", argLength: 2, reg: gp21, asm: "ORR", aux: "Int64"},                    // arg0 | arg1>>生长素，无符号移位，生长素应在0到63之间。
		{name: "ORshiftRA", argLength: 2, reg: gp21, asm: "ORR", aux: "Int64"},                    // arg0 | arg1>>生长素，符号移位，生长素应在0到63之间。
		{name: "ORshiftRO", argLength: 2, reg: gp21, asm: "ORR", aux: "Int64"},                    // arg0 | arg1 ROR生长素，符号移位，生长素应在0到63之间。
		{name: "XORshiftLL", argLength: 2, reg: gp21, asm: "EOR", aux: "Int64"},                   // arg0^arg1<<生长素，生长素应该在0到63之间。
		{name: "XORshiftRL", argLength: 2, reg: gp21, asm: "EOR", aux: "Int64"},                   // arg0^arg1>>生长素，无符号移位，生长素应该在0到63之间。
		{name: "XORshiftRA", argLength: 2, reg: gp21, asm: "EOR", aux: "Int64"},                   // arg0^arg1>>生长素，符号移位，生长素应在0到63之间。
		{name: "XORshiftRO", argLength: 2, reg: gp21, asm: "EOR", aux: "Int64"},                   // arg0^arg1 ROR生长素，符号移位，生长素应在0到63之间。
		{name: "BICshiftLL", argLength: 2, reg: gp21, asm: "BIC", aux: "Int64"},                   // arg0&^（arg1<<生长素），生长素应在0到63之间。
		{name: "BICshiftRL", argLength: 2, reg: gp21, asm: "BIC", aux: "Int64"},                   // arg0&^（arg1>>生长素），无符号移位，生长素应在0到63之间。
		{name: "BICshiftRA", argLength: 2, reg: gp21, asm: "BIC", aux: "Int64"},                   // arg0&^（arg1>>生长素），符号移位，生长素应在0到63之间。
		{name: "BICshiftRO", argLength: 2, reg: gp21, asm: "BIC", aux: "Int64"},                   // arg0&^（arg1 ROR生长素），符号移位，生长素应在0到63之间。
		{name: "EONshiftLL", argLength: 2, reg: gp21, asm: "EON", aux: "Int64"},                   // arg0^^（arg1<<生长素），生长素应该在0到63之间。
		{name: "EONshiftRL", argLength: 2, reg: gp21, asm: "EON", aux: "Int64"},                   // arg0^^（arg1>>生长素），无符号移位，生长素应在0到63之间。
		{name: "EONshiftRA", argLength: 2, reg: gp21, asm: "EON", aux: "Int64"},                   // arg0^^（arg1>>生长素），符号移位，生长素应在0到63之间。
		{name: "EONshiftRO", argLength: 2, reg: gp21, asm: "EON", aux: "Int64"},                   // arg0^^（arg1 ROR生长素），有符号移位，生长素应在0到63之间。
		{name: "ORNshiftLL", argLength: 2, reg: gp21, asm: "ORN", aux: "Int64"},                   // arg0 | ^（arg1<<生长素），生长素应在0到63之间。
		{name: "ORNshiftRL", argLength: 2, reg: gp21, asm: "ORN", aux: "Int64"},                   // arg0 | ^（arg1>>生长素），无符号移位，生长素应在0到63之间。
		{name: "ORNshiftRA", argLength: 2, reg: gp21, asm: "ORN", aux: "Int64"},                   // arg0 | ^（arg1>>生长素），符号移位，生长素应在0到63之间。
		{name: "ORNshiftRO", argLength: 2, reg: gp21, asm: "ORN", aux: "Int64"},                   // arg0 | ^（arg1 ROR生长素），符号移位，生长素应在0到63之间。
		{name: "CMPshiftLL", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int64", typ: "Flags"}, // arg0与arg1相比<<生长素，生长素应在0到63之间。
		{name: "CMPshiftRL", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int64", typ: "Flags"}, // arg0与arg1比较>>生长素，无符号移位，生长素应在0到63之间。
		{name: "CMPshiftRA", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int64", typ: "Flags"}, // arg0与arg1比较>>生长素，有符号移位，生长素应在0到63之间。
		{name: "CMNshiftLL", argLength: 2, reg: gp2flags, asm: "CMN", aux: "Int64", typ: "Flags"}, // /（arg0+arg1<<生长素）与0相比，生长素应在0到63之间。
		{name: "CMNshiftRL", argLength: 2, reg: gp2flags, asm: "CMN", aux: "Int64", typ: "Flags"}, // /（arg0+arg1>>生长素）与0相比，无符号移位，生长素应该在0到63之间。
		{name: "CMNshiftRA", argLength: 2, reg: gp2flags, asm: "CMN", aux: "Int64", typ: "Flags"}, // /（arg0+arg1>>生长素）与0相比，有符号移位，生长素应该在0到63之间。
		{name: "TSTshiftLL", argLength: 2, reg: gp2flags, asm: "TST", aux: "Int64", typ: "Flags"}, // /（arg0和arg1<<生长素）与0相比，生长素应在0到63之间。
		{name: "TSTshiftRL", argLength: 2, reg: gp2flags, asm: "TST", aux: "Int64", typ: "Flags"}, // /（arg0和arg1>>生长素）与0相比，无符号移位，生长素应该在0到63之间。
		{name: "TSTshiftRA", argLength: 2, reg: gp2flags, asm: "TST", aux: "Int64", typ: "Flags"}, // /（arg0和arg1>>生长素）与0相比，有符号移位，生长素应该在0到63之间。
		{name: "TSTshiftRO", argLength: 2, reg: gp2flags, asm: "TST", aux: "Int64", typ: "Flags"}, // /（arg0和arg1 ROR生长素）与0相比，有符号移位，生长素应在0到63之间。

		// 位域操作
		// 对于所有位域操作，lsb是auxInt>>8，宽度是auxInt&0xff 
		// 将arg1的低宽度位插入从位lsb开始的结果，从arg0复制其他位
		{name: "BFI", argLength: 2, reg: gp21nog, asm: "BFI", aux: "ARM64BitField", resultInArg0: true},
		// 提取从位lsb开始的arg1的宽度位，并在结果的低端插入，从arg0复制其他位
		{name: "BFXIL", argLength: 2, reg: gp21nog, asm: "BFXIL", aux: "ARM64BitField", resultInArg0: true},
		// 将arg0的低宽度位插入从位lsb开始的结果中，插入位字段左侧的位设置为插入位字段的高/符号位，右侧的位归零
		{name: "SBFIZ", argLength: 1, reg: gp11, asm: "SBFIZ", aux: "ARM64BitField"},
		// 从位lsb开始提取arg0的宽度位，并在结果的低端插入，剩余高位设置为提取位字段
		{name: "SBFX", argLength: 1, reg: gp11, asm: "SBFX", aux: "ARM64BitField"},
		// 将arg0的低宽度位插入从位lsb开始的结果中，插入位字段左侧和右侧的位归零
		{name: "UBFIZ", argLength: 1, reg: gp11, asm: "UBFIZ", aux: "ARM64BitField"},
		// 从位lsb开始提取arg0的宽度位，并在结果的低端插入，剩余高位为零
		{name: "UBFX", argLength: 1, reg: gp11, asm: "UBFX", aux: "ARM64BitField"},

		// 移动
		{name: "MOVDconst", argLength: 0, reg: gp01, aux: "Int64", asm: "MOVD", typ: "UInt64", rematerializeable: true},      // 从auxint 
		{name: "FMOVSconst", argLength: 0, reg: fp01, aux: "Float64", asm: "FMOVS", typ: "Float32", rematerializeable: true}, // 将auxint转换为64位浮点，转换为32位浮点
		{name: "FMOVDconst", argLength: 0, reg: fp01, aux: "Float64", asm: "FMOVD", typ: "Float64", rematerializeable: true}, // 将auxint转换为64位浮点

		{name: "MOVDaddr", argLength: 1, reg: regInfo{inputs: []regMask{buildReg("SP") | buildReg("SB")}, outputs: []regMask{gp}}, aux: "SymOff", asm: "MOVD", rematerializeable: true, symEffect: "Addr"}, // arg0+auxint+aux。（*gc.Sym），arg0=SP/SB 

		{name: "MOVBload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVB", typ: "Int8", faultOnNilArg0: true, symEffect: "Read"},      // 从arg0+auxInt+aux加载。arg1=mem。
		{name: "MOVBUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVBU", typ: "UInt8", faultOnNilArg0: true, symEffect: "Read"},   // 从arg0+auxInt+aux加载。arg1=mem。
		{name: "MOVHload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVH", typ: "Int16", faultOnNilArg0: true, symEffect: "Read"},     // 从arg0+生长素+辅助加载。arg1=mem。
		{name: "MOVHUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVHU", typ: "UInt16", faultOnNilArg0: true, symEffect: "Read"},  // 从arg0+生长素+辅助加载。arg1=mem。
		{name: "MOVWload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVW", typ: "Int32", faultOnNilArg0: true, symEffect: "Read"},     // 从arg0+生长素+aux加载。arg1=mem。
		{name: "MOVWUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVWU", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"},  // 从arg0+生长素+辅助加载。arg1=mem。
		{name: "MOVDload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVD", typ: "UInt64", faultOnNilArg0: true, symEffect: "Read"},    // 从arg0+auxInt+aux加载。arg1=mem。
		{name: "FMOVSload", argLength: 2, reg: fpload, aux: "SymOff", asm: "FMOVS", typ: "Float32", faultOnNilArg0: true, symEffect: "Read"}, // 从arg0+auxInt+aux加载。arg1=mem。
		{name: "FMOVDload", argLength: 2, reg: fpload, aux: "SymOff", asm: "FMOVD", typ: "Float64", faultOnNilArg0: true, symEffect: "Read"}, // 从arg0+生长素+辅助加载。arg1=mem。

		// 寄存器索引加载
		{name: "MOVDloadidx", argLength: 3, reg: gp2load, asm: "MOVD", typ: "UInt64"},    // 从arg0+arg1加载64位dword，arg2=mem。
		{name: "MOVWloadidx", argLength: 3, reg: gp2load, asm: "MOVW", typ: "Int32"},     // 从arg0+arg1加载32位字，符号扩展到64位，arg2=mem。
		{name: "MOVWUloadidx", argLength: 3, reg: gp2load, asm: "MOVWU", typ: "UInt32"},  // 从arg0+arg1加载32位字，零扩展到64位，arg2=mem。
		{name: "MOVHloadidx", argLength: 3, reg: gp2load, asm: "MOVH", typ: "Int16"},     // 从arg0+arg1加载16位字，符号扩展到64位，arg2=mem。
		{name: "MOVHUloadidx", argLength: 3, reg: gp2load, asm: "MOVHU", typ: "UInt16"},  // 从arg0+arg1加载16位字，零扩展到64位，arg2=mem。
		{name: "MOVBloadidx", argLength: 3, reg: gp2load, asm: "MOVB", typ: "Int8"},      // 从arg0+arg1加载8位字，符号扩展到64位，arg2=mem。
		{name: "MOVBUloadidx", argLength: 3, reg: gp2load, asm: "MOVBU", typ: "UInt8"},   // 从arg0+arg1加载8位字，零扩展到64位，arg2=mem。
		{name: "FMOVSloadidx", argLength: 3, reg: fp2load, asm: "FMOVS", typ: "Float32"}, // 从arg0+arg1加载32位浮点，arg2=mem。
		{name: "FMOVDloadidx", argLength: 3, reg: fp2load, asm: "FMOVD", typ: "Float64"}, // 从arg0+arg1加载64位浮点，arg2=mem。

		// 移位寄存器索引加载
		{name: "MOVHloadidx2", argLength: 3, reg: gp2load, asm: "MOVH", typ: "Int16"},     // 从arg0+arg1*2加载16位半字，符号扩展到64位，arg2=mem。
		{name: "MOVHUloadidx2", argLength: 3, reg: gp2load, asm: "MOVHU", typ: "UInt16"},  // 从arg0+arg1*2加载16位半字，零扩展到64位，arg2=mem。
		{name: "MOVWloadidx4", argLength: 3, reg: gp2load, asm: "MOVW", typ: "Int32"},     // 从arg0+arg1*4加载32位字，符号扩展到64位，arg2=mem。
		{name: "MOVWUloadidx4", argLength: 3, reg: gp2load, asm: "MOVWU", typ: "UInt32"},  // 从arg0+arg1*4加载32位字，零扩展到64位，arg2=mem。
		{name: "MOVDloadidx8", argLength: 3, reg: gp2load, asm: "MOVD", typ: "UInt64"},    // 从arg0+arg1*8加载64位双字，arg2=mem。
		{name: "FMOVSloadidx4", argLength: 3, reg: fp2load, asm: "FMOVS", typ: "Float32"}, // 从arg0+arg1*4加载32位浮点，arg2=mem。
		{name: "FMOVDloadidx8", argLength: 3, reg: fp2load, asm: "FMOVD", typ: "Float64"}, // 从arg0+arg1*8加载64位浮点，arg2=mem。

		{name: "MOVBstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVB", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"},   // 将arg1的1字节存储到arg0+auxInt+aux。arg2=mem。
		{name: "MOVHstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVH", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"},   // 存储arg1到arg0+auxInt+aux的2个字节。arg2=mem。
		{name: "MOVWstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVW", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"},   // 将4字节的arg1存储到arg0+auxInt+aux。arg2=mem。
		{name: "MOVDstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVD", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"},   // 将8字节的arg1存储到arg0+auxInt+aux。arg2=mem。
		{name: "STP", argLength: 4, reg: gpstore2, aux: "SymOff", asm: "STP", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"},         // 将arg1和arg2的16字节存储到arg0+auxInt+aux。arg3=mem。
		{name: "FMOVSstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "FMOVS", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将arg1的4个字节存储到arg0+auxInt+aux。arg2=mem。
		{name: "FMOVDstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "FMOVD", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将8字节的arg1存储到arg0+auxInt+aux。arg2=mem。

		// 寄存器索引存储
		{name: "MOVBstoreidx", argLength: 4, reg: gpstore2, asm: "MOVB", typ: "Mem"},   // 将arg2的1字节存储到arg0+arg1，arg3=mem。
		{name: "MOVHstoreidx", argLength: 4, reg: gpstore2, asm: "MOVH", typ: "Mem"},   // 将arg2的2个字节存储到arg0+arg1，arg3=mem。
		{name: "MOVWstoreidx", argLength: 4, reg: gpstore2, asm: "MOVW", typ: "Mem"},   // 将arg2的4个字节存储到arg0+arg1，arg3=mem。
		{name: "MOVDstoreidx", argLength: 4, reg: gpstore2, asm: "MOVD", typ: "Mem"},   // 将8字节的arg2存储到arg0+arg1，arg3=mem。
		{name: "FMOVSstoreidx", argLength: 4, reg: fpstore2, asm: "FMOVS", typ: "Mem"}, // 将arg2的32位浮点存储到arg0+arg1，arg3=mem。
		{name: "FMOVDstoreidx", argLength: 4, reg: fpstore2, asm: "FMOVD", typ: "Mem"}, // 将arg2的64位浮点存储到arg0+arg1，arg3=mem。

		// 移位寄存器索引存储
		{name: "MOVHstoreidx2", argLength: 4, reg: gpstore2, asm: "MOVH", typ: "Mem"},   // 将arg2的2字节存储到arg0+arg1*2，arg3=mem。
		{name: "MOVWstoreidx4", argLength: 4, reg: gpstore2, asm: "MOVW", typ: "Mem"},   // 将arg2的4个字节存储到arg0+arg1*4，arg3=mem。
		{name: "MOVDstoreidx8", argLength: 4, reg: gpstore2, asm: "MOVD", typ: "Mem"},   // 将8字节的arg2存储到arg0+arg1*8，arg3=mem。
		{name: "FMOVSstoreidx4", argLength: 4, reg: fpstore2, asm: "FMOVS", typ: "Mem"}, // 将arg2的32位浮点存储到arg0+arg1*4，arg3=mem。
		{name: "FMOVDstoreidx8", argLength: 4, reg: fpstore2, asm: "FMOVD", typ: "Mem"}, // 将arg2的64位浮点存储到arg0+arg1*8，arg3=mem。

		{name: "MOVBstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVB", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将0的1字节存储到arg0+auxInt+aux。arg1=mem。
		{name: "MOVHstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVH", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将0的2个字节存储到arg0+auxInt+aux。arg1=mem。
		{name: "MOVWstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVW", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将4字节的0存储到arg0+auxInt+aux。arg1=mem。
		{name: "MOVDstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVD", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将8字节的零存储到arg0+auxInt+aux。arg1=mem。
		{name: "MOVQstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "STP", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"},  // 将16字节的零存储到arg0+auxInt+aux。arg1=mem。

		// 寄存器索引存储零
		{name: "MOVBstorezeroidx", argLength: 3, reg: gpstore, asm: "MOVB", typ: "Mem"}, // 将0的1字节存储到arg0+arg1，arg2=mem。
		{name: "MOVHstorezeroidx", argLength: 3, reg: gpstore, asm: "MOVH", typ: "Mem"}, // 将0的2个字节存储到arg0+arg1，arg2=mem。
		{name: "MOVWstorezeroidx", argLength: 3, reg: gpstore, asm: "MOVW", typ: "Mem"}, // 将0的4个字节存储到arg0+arg1，arg2=mem。
		{name: "MOVDstorezeroidx", argLength: 3, reg: gpstore, asm: "MOVD", typ: "Mem"}, // 将8个字节的零存储到arg0+arg1，arg2=mem。

		// 移位寄存器索引存储零
		{name: "MOVHstorezeroidx2", argLength: 3, reg: gpstore, asm: "MOVH", typ: "Mem"}, // 将0的2个字节存储到arg0+arg1*2，arg2=mem。
		{name: "MOVWstorezeroidx4", argLength: 3, reg: gpstore, asm: "MOVW", typ: "Mem"}, // 将0的4个字节存储到arg0+arg1*4，arg2=mem。
		{name: "MOVDstorezeroidx8", argLength: 3, reg: gpstore, asm: "MOVD", typ: "Mem"}, // 将8个字节的零存储到arg0+arg1*8，arg2=mem。

		{name: "FMOVDgpfp", argLength: 1, reg: gpfp, asm: "FMOVD"}, // 将int64移动到浮点64（无转换）
		{name: "FMOVDfpgp", argLength: 1, reg: fpgp, asm: "FMOVD"}, // 将浮点64移动到int64（无转换）
		{name: "FMOVSgpfp", argLength: 1, reg: gpfp, asm: "FMOVS"}, // 将32位从int移动到float reg（无转换）
		{name: "FMOVSfpgp", argLength: 1, reg: fpgp, asm: "FMOVS"}, // 将32位从浮点移动到int reg，零扩展（无转换）

		// 转换
		{name: "MOVBreg", argLength: 1, reg: gp11, asm: "MOVB"},   // 从arg0移动，从字节
		{name: "MOVBUreg", argLength: 1, reg: gp11, asm: "MOVBU"}, // /扩展的符号从arg0移动，从字节
		{name: "MOVHreg", argLength: 1, reg: gp11, asm: "MOVH"},   // /扩展的符号从arg0移动，从半
		{name: "MOVHUreg", argLength: 1, reg: gp11, asm: "MOVHU"}, // /扩展的符号从arg0移动，从半
		{name: "MOVWreg", argLength: 1, reg: gp11, asm: "MOVW"},   // /扩展的符号从arg0移动，从单词
		{name: "MOVWUreg", argLength: 1, reg: gp11, asm: "MOVWU"}, // /扩展的符号从arg0移动，unsign扩展自单词
		{name: "MOVDreg", argLength: 1, reg: gp11, asm: "MOVD"},   // 从arg0移动至

		{name: "MOVDnop", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{gp}}, resultInArg0: true}, // 否，返回同一寄存器中的arg0 

		{name: "SCVTFWS", argLength: 1, reg: gpfp, asm: "SCVTFWS"},   // int32->float32 
		{name: "SCVTFWD", argLength: 1, reg: gpfp, asm: "SCVTFWD"},   // int32->float64 
		{name: "UCVTFWS", argLength: 1, reg: gpfp, asm: "UCVTFWS"},   // uint32->float32 
		{name: "UCVTFWD", argLength: 1, reg: gpfp, asm: "UCVTFWD"},   // uint32->float64 
		{name: "SCVTFS", argLength: 1, reg: gpfp, asm: "SCVTFS"},     // int64->float32 
		{name: "UCVTFS", argLength: 1, reg: gpfp, asm: "UCVTFS"},     // uint64->float32->
		{name: "UCVTFD", argLength: 1, reg: gpfp, asm: "UCVTFD"},     // uint64 
		{name: "FCVTZUSW", argLength: 1, reg: fpgp, asm: "FCVTZUSW"}, // float32->uint32-
		{name: "FCVTZUDW", argLength: 1, reg: fpgp, asm: "FCVTZUDW"}, // float64->uint32-
		{name: "FCVTZSS", argLength: 1, reg: fpgp, asm: "FCVTZSS"},   // float32->int64-
		{name: "FCVTZSD", argLength: 1, reg: fpgp, asm: "FCVTZSD"},   // float64->int64-
		{name: "FCVTZUS", argLength: 1, reg: fpgp, asm: "FCVTZUS"},   // float32->uint64-

		{name: "FRINTAD", argLength: 1, reg: fp11, asm: "FRINTAD"},
		{name: "FRINTMD", argLength: 1, reg: fp11, asm: "FRINTMD"},
		{name: "FRINTND", argLength: 1, reg: fp11, asm: "FRINTND"},
		{name: "FRINTPD", argLength: 1, reg: fp11, asm: "FRINTPD"},
		{name: "FRINTZD", argLength: 1, reg: fp11, asm: "FRINTZD"},

		// 条件指令；生长素是
		// arm64比较伪操作之一（LessThan、LessThanU等）
		{name: "CSEL", argLength: 3, reg: gp2flags1, asm: "CSEL", aux: "CCop"},   // 生长素（标志）？arg0:arg1 
		{name: "CSEL0", argLength: 2, reg: gp1flags1, asm: "CSEL", aux: "CCop"},  // 生长素（旗帜）？arg0:0 
		{name: "CSINC", argLength: 3, reg: gp2flags1, asm: "CSINC", aux: "CCop"}, // 生长素（旗帜）？arg0:arg1+1 
		{name: "CSINV", argLength: 3, reg: gp2flags1, asm: "CSINV", aux: "CCop"}, // 生长素（标志）？arg0:^arg1 
		{name: "CSNEG", argLength: 3, reg: gp2flags1, asm: "CSNEG", aux: "CCop"}, // 生长素（旗帜）？arg0:-arg1 
		{name: "CSETM", argLength: 1, reg: readflags, asm: "CSETM", aux: "CCop"}, // 生长素（旗帜）-1:0 

		// 函数调用
		{name: "CALLstatic", argLength: -1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true},                                               // 调用静态函数aux。（*obj.LSym）。last arg=mem，auxint=argsize，返回mem 
		{name: "CALLtail", argLength: -1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true, tailCall: true},                                 // tail call static function aux。（*obj.LSym）。last arg=mem，auxint=argsize，返回mem 
		{name: "CALLclosure", argLength: -1, reg: regInfo{inputs: []regMask{gpsp, buildReg("R26"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // 通过闭包调用函数。arg0=codeptr，arg1=closure，last arg=mem，auxint=argsize，返回mem 
		{name: "CALLinter", argLength: -1, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true},                         // 通过指针调用fn。arg0=codeptr，last arg=mem，auxint=argsize，返回mem 

		// 伪操作
		{name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpg}}, nilCheck: true, faultOnNilArg0: true}, // 如果arg0为零，则出现恐慌。arg1=mem。

		{name: "Equal", argLength: 1, reg: readflags},            // bool，true标志编码x==y，否则为false。
		{name: "NotEqual", argLength: 1, reg: readflags},         // bool，真标志编码x=否则就错了。
		{name: "LessThan", argLength: 1, reg: readflags},         // bool，true标志编码有符号x<y，否则为false。
		{name: "LessEqual", argLength: 1, reg: readflags},        // bool，true标志编码有符号的x<=y，否则为false。
		{name: "GreaterThan", argLength: 1, reg: readflags},      // bool，true标志编码有符号的x>y，否则为false。
		{name: "GreaterEqual", argLength: 1, reg: readflags},     // bool，true标志编码有符号x>=y，否则为false。
		{name: "LessThanU", argLength: 1, reg: readflags},        // bool，true标志编码无符号x<y，否则为false。
		{name: "LessEqualU", argLength: 1, reg: readflags},       // bool，true标志编码无符号x<=y，否则为false。
		{name: "GreaterThanU", argLength: 1, reg: readflags},     // bool，true标志编码无符号x>y，否则为false。
		{name: "GreaterEqualU", argLength: 1, reg: readflags},    // bool，true标志编码无符号x>=y，否则为false。
		{name: "LessThanF", argLength: 1, reg: readflags},        // bool，true标志编码浮点x<y，否则为false。
		{name: "LessEqualF", argLength: 1, reg: readflags},       // bool，true标志编码浮点x<=y，否则为false。
		{name: "GreaterThanF", argLength: 1, reg: readflags},     // bool，true标志编码浮点x>y，否则为false。
		{name: "GreaterEqualF", argLength: 1, reg: readflags},    // bool，true标志编码浮点x>=y，否则为false。
		{name: "NotLessThanF", argLength: 1, reg: readflags},     // bool，真标志编码浮点x>=y | | x与y无序，否则为假。
		{name: "NotLessEqualF", argLength: 1, reg: readflags},    // bool，真标志编码浮点x>y | | x与y无序，否则为假。
		{name: "NotGreaterThanF", argLength: 1, reg: readflags},  // bool，真标志编码浮点x<=y | | x与y无序，否则为假。
		{name: "NotGreaterEqualF", argLength: 1, reg: readflags}, // bool，真标志编码浮点x<y | | x与y无序，否则为假。
		// duffzero 
		// arg0=内存地址到零
		// arg1=mem 
		// auxint=offset到duffzero代码中开始执行
		// 返回mem 
		// R20更改为副作用
		// R16和R17可能被链接器蹦床撞击。
		{
			name:      "DUFFZERO",
			aux:       "Int64",
			argLength: 2,
			reg: regInfo{
				inputs:   []regMask{buildReg("R20")},
				clobbers: buildReg("R16 R17 R20 R30"),
			},
			faultOnNilArg0: true,
			unsafePoint:    true, // DUFFZERO周围的FP维护可能会被中断中断
		},

		// large zeroing 
		// arg0=内存地址为零（在R16又称arm64.REGT1中，作为副作用更改）
		// arg1=最后16字节单元的地址为零
		// arg2=mem 
		// 返回mem 
		// CMP Rarg1，R16 
		// BLE-2（PC）
		// 注意：内存的结尾可能不是有效的指针。如果洒了就有问题了。
		// 内存的末尾-16是区域为零的，可以溢出。
		{
			name:      "LoweredZero",
			argLength: 3,
			reg: regInfo{
				inputs:   []regMask{buildReg("R16"), gp},
				clobbers: buildReg("R16"),
			},
			clobberFlags:   true,
			faultOnNilArg0: true,
		},

		// duffcopy 
		// arg0=dst内存地址（在R21中，更改为副作用）
		// arg1=src内存地址（在R20中，更改为副作用）
		// arg2=mem 
		// auxint=偏移到duffcopy代码中开始执行
		// 返回mem 
		// R20，R21因副作用
		// R16和R17可能被连接器蹦床击倒。
		{
			name:      "DUFFCOPY",
			aux:       "Int64",
			argLength: 3,
			reg: regInfo{
				inputs:   []regMask{buildReg("R21"), buildReg("R20")},
				clobbers: buildReg("R16 R17 R20 R21 R26 R30"),
			},
			faultOnNilArg0: true,
			faultOnNilArg1: true,
			unsafePoint:    true, // DUFFCOPY周围的FP维护可能会被中断中断
		},

		// large move 
		// arg0=dst内存地址（在R17又名arm64.reglt2中，更改为副作用）
		// arg1=src内存地址（在R16又名arm64.reglt1中，更改为副作用）
		// arg3=mem 
		// 返回mem 
		// MOVD。第8页（R16），Rtmp 
		// MOVD。P Rtmp，8（R17）
		// CMP Rarg2，R16 
		// BLE-3（PC）
		// 注意：src的结尾可能不是有效的指针。如果洒了就有问题了。
		// src-8的末端在要复制的区域内，可以溢出。
		{
			name:      "LoweredMove",
			argLength: 4,
			reg: regInfo{
				inputs:   []regMask{buildReg("R17"), buildReg("R16"), gp},
				clobbers: buildReg("R16 R17"),
			},
			clobberFlags:   true,
			faultOnNilArg0: true,
			faultOnNilArg1: true,
		},

		// 调度器确保LoweredGetClosurePtr只出现在entry块中，
		// 并将其排序到块的最开始，以防止其他
		// 使用R26（arm64.REGCTXT，闭包指针）
		{name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{buildReg("R26")}}, zeroWidth: true},

		// LoweredGetCallerSP返回当前函数调用方的SP。
		{name: "LoweredGetCallerSP", reg: gp01, rematerializeable: true},

		// LoweredGetCallerPC计算其“调用者”将返回的PC。
		// 也就是说，如果f调用g“calls”getcallerpc，
		// 结果应该是g将返回的f内的PC。
		// 请参阅运行时/stubs。进行更详细的讨论。
		{name: "LoweredGetCallerPC", reg: gp01, rematerializeable: true},

		// 常量标志值。
		// 注意：浮点
		// 比较有一个“无序”的结果，但我们还没有使用这种野兽。
		// 此op供重写规则临时使用。它
		// 不能出现在生成的程序集中。
		{name: "FlagConstant", aux: "FlagConstant"},

		// /（反向标志（CMP a b））==（CMP b a）
		// InvertFlags是一个伪操作，不能出现在程序集输出中。
		{name: "InvertFlags", argLength: 1}, // arg0的反向

		// 原子负载。
		// 从arg0加载。arg1=mem。生长素必须为零。
		// 返回<value，memory>，因此可以与其他加载一起正确排序。
		{name: "LDAR", argLength: 2, reg: gpload, asm: "LDAR", faultOnNilArg0: true},
		{name: "LDARB", argLength: 2, reg: gpload, asm: "LDARB", faultOnNilArg0: true},
		{name: "LDARW", argLength: 2, reg: gpload, asm: "LDARW", faultOnNilArg0: true},

		// 原子商店。
		// 存储arg1到arg0。arg2=mem。返回内存。生长素必须为零。
		{name: "STLRB", argLength: 3, reg: gpstore, asm: "STLRB", faultOnNilArg0: true, hasSideEffects: true},
		{name: "STLR", argLength: 3, reg: gpstore, asm: "STLR", faultOnNilArg0: true, hasSideEffects: true},
		{name: "STLRW", argLength: 3, reg: gpstore, asm: "STLRW", faultOnNilArg0: true, hasSideEffects: true},

		// 原子交换。
		// 将arg1存储到arg0。arg2=mem。返回<old content of*arg0，memory>。生长素必须为零。
		// LDAXR（Rarg0），Rout 
		// STLXR Rarg1（Rarg0），Rtmp 
		// CBNZ Rtmp，-2（PC）
		{name: "LoweredAtomicExchange64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
		{name: "LoweredAtomicExchange32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},

		// 原子交换变体。
		// 存储arg1到arg0。arg2=mem。返回<old content of*arg0，memory>。生长素必须为零。
		// 切换Rarg1（Rarg0），路由
		{name: "LoweredAtomicExchange64Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
		{name: "LoweredAtomicExchange32Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},

		// 原子添加。
		// /*arg0+=arg1。arg2=mem。返回<新内容*arg0，内存>。生长素必须为零。
		// LDAXR（Rarg0），Rout 
		// 添加Rarg1，Rout 
		// STLXR Rout，（Rarg0），Rtmp 
		// CBNZ Rtmp，-3（PC）
		{name: "LoweredAtomicAdd64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
		{name: "LoweredAtomicAdd32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},

		// 原子添加变体。
		// /*arg0+=arg1。arg2=mem。返回<新内容*arg0，内存>。生长素必须为零。
		// LDADDAL（Rarg0），Rarg1，Rout 
		// 添加Rarg1，Rout 
		{name: "LoweredAtomicAdd64Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
		{name: "LoweredAtomicAdd32Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},

		// 原子比较和交换。
		// arg0=指针，arg1=旧值，arg2=新值，arg3=内存。生长素必须为零。
		// if*arg0==arg1{
		// *arg0=arg2 
		// 返回（真，内存）
		// }否则{
		// 返回（假，内存）
		// /}，Rtmp 
		// CBNZ Rtmp，-4（PC）
		// CSET EQ，Rout 
		{name: "LoweredAtomicCas64", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
		{name: "LoweredAtomicCas32", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},

		// 原子比较和交换变量。
		// arg0=指针，arg1=旧值，arg2=新值，arg3=内存。生长素必须为零。
		// if*arg0==arg1{
		// *arg0=arg2 
		// return（true，memory）
		// }else{
		// return false，memory）
		// }，Rout 
		{name: "LoweredAtomicCas64Variant", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
		{name: "LoweredAtomicCas32Variant", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},

		// 原子和/或。
		// /*arg0&=（|=）arg1。arg2=mem。返回<新内容*arg0，内存>。生长素必须为零。
		// LDAXR（Rarg0），Rout 
		// 和/或Rarg1，Rout 
		// STLXR Rout，（Rarg0），Rtmp 
		// CBNZ Rtmp，-3（PC）
		{name: "LoweredAtomicAnd8", argLength: 3, reg: gpxchg, resultNotInArgs: true, asm: "AND", typ: "(UInt8,Mem)", faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
		{name: "LoweredAtomicAnd32", argLength: 3, reg: gpxchg, resultNotInArgs: true, asm: "AND", typ: "(UInt32,Mem)", faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
		{name: "LoweredAtomicOr8", argLength: 3, reg: gpxchg, resultNotInArgs: true, asm: "ORR", typ: "(UInt8,Mem)", faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
		{name: "LoweredAtomicOr32", argLength: 3, reg: gpxchg, resultNotInArgs: true, asm: "ORR", typ: "(UInt32,Mem)", faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},

		// 原子和/或变体。
		// /*arg0&=（|=）arg1。arg2=mem。返回<新的*arg0内容，内存>。生长素必须为零。
		// 和：
		// MNV Rarg1，Rtemp 
		// LDANDALB Rtemp，（Rarg0），Rout 
		// 和Rarg1，Rout 
		// 或：
		// LDORALB Rarg1，（Rarg0），Rout 
		// ORR Rarg1，Rout 
		{name: "LoweredAtomicAnd8Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, typ: "(UInt8,Mem)", faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
		{name: "LoweredAtomicAnd32Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, typ: "(UInt32,Mem)", faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
		{name: "LoweredAtomicOr8Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, typ: "(UInt8,Mem)", faultOnNilArg0: true, hasSideEffects: true},
		{name: "LoweredAtomicOr32Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, typ: "(UInt32,Mem)", faultOnNilArg0: true, hasSideEffects: true},

		// 如果需要，它会保存所有GP寄存器，
		// 但会关闭R30（LR），因为这是一个调用。
		// R16和R17可能会被链接器蹦床撞到。
		{name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("R2"), buildReg("R3")}, clobbers: (callerSave &^ gpg) | buildReg("R16 R17 R30")}, clobberFlags: true, aux: "Sym", symEffect: "None"},

		// 其中有三个函数，因此它们可以有三个不同的寄存器输入。
		// 当我们检查0<=c<=cap（A），然后检查0<=b<=c（b），然后检查0<=A<=b（c）时，我们希望
		// 默认寄存器匹配，所以我们不需要不必要地复制寄存器。
		{name: "LoweredPanicBoundsA", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r2, r3}}, typ: "Mem", call: true}, // arg0=idx，arg1=len，arg2=mem，返回内存。AuxInt包含报告代码（参见generic.go中的PanicBounds）。
		{name: "LoweredPanicBoundsB", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r1, r2}}, typ: "Mem", call: true}, // arg0=idx，arg1=len，arg2=mem，返回内存。AuxInt包含报告代码（参见generic.go中的PanicBounds）。
		{name: "LoweredPanicBoundsC", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r0, r1}}, typ: "Mem", call: true}, // arg0=idx，arg1=len，arg2=mem，返回内存。AuxInt包含报告代码（参见generic.go中的PanicBounds）。

		// 预取指令
		// 使用选项aux预取arg0地址。arg0=addr，arg1=memory，aux=option。
		{name: "PRFM", argLength: 2, aux: "Int64", reg: prefreg, asm: "PRFM", hasSideEffects: true},

		// 发布障碍
		{name: "DMB", argLength: 1, aux: "Int64", asm: "DMB", hasSideEffects: true}, // Do数据障碍。arg0=内存，aux=选项。
	}

	blocks := []blockData{
		{name: "EQ", controls: 1},
		{name: "NE", controls: 1},
		{name: "LT", controls: 1},
		{name: "LE", controls: 1},
		{name: "GT", controls: 1},
		{name: "GE", controls: 1},
		{name: "ULT", controls: 1},
		{name: "ULE", controls: 1},
		{name: "UGT", controls: 1},
		{name: "UGE", controls: 1},
		{name: "Z", controls: 1},                  // 控件==0（使用寄存器而不是标志）
		{name: "NZ", controls: 1},                 // 控件！=0 
		{name: "ZW", controls: 1},                 // 控件==0，32位
		{name: "NZW", controls: 1},                // 控件！=0，32位
		{name: "TBZ", controls: 1, aux: "Int64"},  // 控制和（1<<生长素）==0 
		{name: "TBNZ", controls: 1, aux: "Int64"}, // 控制和（1<<生长素）！=0 
		{name: "FLT", controls: 1},
		{name: "FLE", controls: 1},
		{name: "FGT", controls: 1},
		{name: "FGE", controls: 1},
		{name: "LTnoov", controls: 1}, // /'LT'但不表示溢出
		{name: "LEnoov", controls: 1}, // /'LE'但不表示溢出
		{name: "GTnoov", controls: 1}, // /'GT'但不表示溢出
		{name: "GEnoov", controls: 1}, // /'GE'但不表示溢出
	}

	archs = append(archs, arch{
		name:               "ARM64",
		pkg:                "cmd/internal/obj/arm64",
		genfile:            "../../arm64/ssa.go",
		ops:                ops,
		blocks:             blocks,
		regnames:           regNamesARM64,
		ParamIntRegNames:   "R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15",
		ParamFloatRegNames: "F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15",
		gpregmask:          gp,
		fpregmask:          fp,
		framepointerreg:    -1, // 未使用
		linkreg:            int8(num["R30"]),
	})
}
